﻿using System;
using System.Collections.Generic;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using Abp.Linq.Extensions;
using Abp.ObjectMapping;
using Hicap.AuthorizationServer.Application.Dto;
using Hicap.AuthorizationServer.Application.Dto.Common;
using Hicap.AuthorizationServer.Core.Common;
using Hicap.AuthorizationServer.Core.Identity;
using Hicap.AuthorizationServer.Core.Managers;
using Hicap.AuthorizationServer.Core.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;

namespace Hicap.AuthorizationServer.Application.Sys
{
    public class UserAppService : AuthorizationServerApplicationBase<User, UserListDto, UserEditDto>
    {
        private readonly IUserManager _manager;
        private readonly IObjectMapper _objectMapper;
        private readonly IUserRoleRelatedManager _userRoleRelatedManager;
        private readonly INotificationManager _notificationManager;
        private readonly IRoleManager _roleManager;

        public UserAppService(IUserManager manager,
            IUserRoleRelatedManager userRoleRelatedManager,
            IObjectMapper objectMapper, INotificationManager notificationManager,
            IRoleManager roleManager) : base(manager)
        {
            _manager = manager;
            _objectMapper = objectMapper;
            _userRoleRelatedManager = userRoleRelatedManager;
            _notificationManager = notificationManager;
            _roleManager = roleManager;
        }

        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AllowAnonymous]
        public async Task<UserListDto> Register(UserEditDto input)
        {
            input.IsActive = false;

            var result = await CreateAsync(input);

            if (result != null)
            {
                await NotificationUserActive(result.MapTo<UserListDto>());
            }

            return result;
        }

        private async Task NotificationUserActive(dynamic data)
        {
            await _notificationManager.Echo(NotificationType.UserActive, data);
        }

        /// <summary>
        /// 添加实体方法
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        protected virtual async Task<UserListDto> CreateAsync(UserEditDto input)
        {
            var entity = _objectMapper.Map<User>(input);

            entity.Id = await _manager.InsertAndGetId(entity);

            return entity.MapTo<UserListDto>();
        }

        /// <summary>
        /// 用户激活
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        [HicapAuthorize(SpeicaAuthCode.UserActive)]
        public async Task<UserListDto> ActiveUser(int userId)
        {
            var result = await _manager.ActiveUser(userId);
            return _objectMapper.Map<UserListDto>(result);
        }

        private Task CreatePassword(UserEditDto input, User dbEntity)
        {
            return Task.Run(() =>
            {
                if (!string.IsNullOrEmpty(input.Password))
                    dbEntity.CurPassword = _manager.GetPasswordSha256(input.Password);
            });
        }

        private Task UpdatePassword(UserEditDto input, User dbEntity)
        {
            return _manager.UpdatePassword(input.Password, dbEntity);
        }

        /// <summary>
        /// 管理员修改密码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public Task ResetPasswordForAdmin(UserPasswordEditDTO input)
        {
            return _manager.ResetPasswordForAdmin(Convert.ToInt32(input.Id), input.Password);
        }

        /// <summary>
        /// 普通用户修改密码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public Task ResetPassword(UserPasswordEditDTO input)
        {
            return _manager.ResetPassword(Convert.ToInt32(input.Id), input.Password);
        }

        /// <summary>
        /// 获取User的分页列表信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override async Task<PagedResultDto<UserListDto>> PagedDatas(QueryInput input)
        {
            var query = GetQuery(_manager.GetQuery(null), input);

            var userCount = await query.CountAsync();

            List<User> users = await query
                .OrderBy(input.Sorting)
                .PageBy(input)
                .ToListAsync();

            var userListDtos = users.MapTo<List<UserListDto>>();

            foreach (var userListDto in userListDtos)
            {
                var keys = new List<Expression<Func<UserRoleRelated, dynamic>>>()
                {
                    x => x.User,
                    x => x.Role
                };
                foreach (var userRoleRelated in _userRoleRelatedManager.GetQuery
                    (x => x.User.Id == userListDto.Id))
                {
                    var role = _roleManager.GetRoleById(userRoleRelated.RoleId);
                    var map = role.MapTo<RoleListDto>();
                    map.UserRoleReleateId = userRoleRelated.Id;
                    userListDto.Roles.Add(map);
                }
            }

            return new PagedResultDto<UserListDto>(
                userCount,
                userListDtos
            );
        }
    }
}